﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Text;
using EnCor.Config;
using EnCor.ServiceLocator;
using EnCor.ModuleLoader;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity;
using EnCor.CallingTrack;

namespace EnCor
{
    public class ModuleConfigContext : IModuleContext
    {
        private ModuleConfig _Config;

        private IServiceContainer _ServiceContainer;

        public ModuleConfigContext(IServiceContainer container,ModuleConfig config)
        {
            _ServiceContainer = container;
            _Config = config;
        }

        public IServiceContainer ServiceContainer
        {
            get
            {
                return _ServiceContainer;
            }
        }

        public ModuleConfig Config
        {
            get
            {
                return _Config;
            }
        }

        #region IModuleContext 成员

        public BizService RegisterBizService(BizService service, params Type[] asInterfaces)
        {
            foreach ( Type type in asInterfaces)
            {
                if (!type.IsAssignableFrom(service.GetType()))
                {
                    throw new EnCorException(string.Format("The BizService {0} cannot be registered as {1}", service, type));
                }
                _ServiceContainer.RegisterService(type, service);
            }
            Runtime.RegisterService(service.ServiceId, service);
            return service;
        }

        public BizService BuildService(ServiceConfig serviceConfig, string moduleName)
        {
            UnityContainer container = new UnityContainer();
            container.AddNewExtension<Interception>();
            
            PolicyDefinition policy = container.Configure<Interception>().AddPolicy("serviceTracker");
            policy.AddCallHandler(new ServiceCallHandler());
            policy.AddMatchingRule(new BizServicePublicMethodMatchingRole());
            container.Configure<Interception>().SetDefaultInterceptorFor(serviceConfig.Type, new TransparentProxyInterceptor());
            ServiceBuilder serviceBuilder = new ServiceBuilder(_ServiceContainer);
            BizService bizService = serviceBuilder.BuildService(serviceConfig);
            bizService.ServiceId = moduleName + "$" + serviceConfig.Name;
            BizService wraped = (BizService)container.BuildUp(serviceConfig.Type, bizService);
            return wraped;
        }

        #endregion
    }
}
